

const HIDE = 'hide'
const LAST = 'last'
const GRAY = 'gray'
const INFO = 'info'
const JOIN = 'join'
const CDKEYS = 'cdKeys'

Object.defineProperty(Array.prototype, LAST, {
  get: function () {
    return this.length ? this[this.length - 1] : -1
  }
})

class Utils {
  static _ins
  static get instance(): Utils {
    return this._ins ? this._ins : new Utils;
  }
  constructor() {
    Utils._ins = this
  }

  /**
   * @param name 获取url中参数函数
   */
  getParameterByNameMap = null
  getParameterByName(name) {
    if (!this.getParameterByNameMap) {
      this.getParameterByNameMap = {}
      var interrogationIndex = location.href.indexOf('?') + 1
      var str = interrogationIndex === 0 ? '' : location.href.slice(interrogationIndex)
      if (str) {
        var arr = str.split(/&|%26/)
        arr.forEach(item => {
          var arr = item.split(/=|%3D/)
          var key = arr[0]
          var val = arr[1]
          this.getParameterByNameMap[key] = val
        })
      }
    }
    var params: Object = this.getParameterByNameMap
    return params.hasOwnProperty(name) ? params[name] : null
  }

  /**
   * 获取随机数
   */
  get random(): number {
    return Math.random() * 1000
  }

  /**
   * 获取dom元素的相对浏览器顶部的高度
   */
  getElementTop(element): number {
    var actualTop = element.offsetTop;
    var current = element.offsetParent;
    while (current !== null) {
      actualTop += current.offsetTop;
      current = current.offsetParent;
    }
    return actualTop;
  }

}

class Store {

  static _ins
  static get instance(): Store {
    return this._ins ? this._ins : new Store;
  }
  constructor() {
    Store._ins = this
    this.pre = window.md5.md5(window.app + '', 32).slice(0, this.size)
    this.storage = localStorage
  }

  /**
   * 活动前缀
   */
  private pre: string
  /**
   * 前缀尺寸
   */
  public size: number = 6
  /**
   * localstorage
   */
  private storage: Storage

  /**
   * 获取活动前缀
   */
  getPre() {
    return this.pre
  }

  getStore() {
    var _ = {}
    for (var allName in this.storage) {
      var pre = allName.slice(0, this.size)
      if (pre === this.pre) {
        var name = allName.slice(this.size)
        _[name] = this.getItem(name)
      }
    }
    return _
  }

  setItem(key, value) {
    key = this.pre + key
    value = JSON.stringify({
      value
    })
    this.storage.setItem(key, value)
  }

  getItem(key) {
    key = this.pre + key

    if (this.storage.hasOwnProperty(key)) {
      return JSON.parse(this.storage.getItem(key)).value
    }
    return null
  }

  clear() {
    for (var allName in this.storage) {
      var pre = allName.slice(0, this.size)
      if (pre === this.pre) {
        delete this.storage[allName]
      }
    }
  }

}

class Events {

  static groupId = '5adf1ac790bf7f1a14bf80d8'

  protected _eventIndex: number

  static _actId: string[] = [
    '5ae1c04b90bf7f1a14bf830f',
    '5ae1c08f90bf7f1a14bf8310',
    '5ae2e0b590bf7f1a14bf837e'
  ]

  get actId() {
    return Events._actId[this._eventIndex]
  }

  static _rewardIds: string[][] = [
    [
      '5aeaf75390bf7f1a14bf84f8'
    ],
    [
      '5ae2e08290bf7f1a14bf837d',
      '5ae30b9c90bf7f1a14bf838e',
      '5ae30c1a90bf7f1a14bf8395'
    ],
    [
      '5aeaf82b90bf7f1a14bf90bd',
      '5aeaf88090bf7f1a14bf90c0',
      '5aeaf8dd90bf7f1a14bf90c3',
      '5aeaf94b90bf7f1a14bf90c8',
      '5aeaf98f90bf7f1a14bf90cb',
      '5aeaf9db90bf7f1a14bf90ce',
      '5aeafa4190bf7f1a14bf90db'
    ]
  ]

  get rewardId(): Array<string> {
    return Events._rewardIds[this._eventIndex]
  }

  private _infos: InfoState[] = []
  set info(info) {
    this._infos[this._eventIndex] = info
  }
  get info(): InfoState {
    return this._infos[this._eventIndex]
  }

  private _historys: CdkeyState[][] = []
  set history(history) {
    this._historys[this._eventIndex] = history
  }
  get history(): CdkeyState[] {
    return this._historys[this._eventIndex]
  }

}

class Event3 extends Events {
  static _ins
  static get instance(): Event3 {
    return this._ins ? this._ins : new Event3;
  }
  constructor() {
    super();
    Event3._ins = this
  }

  /**
   * 活动键值
   */
  protected _eventIndex = 2


  queryEvent(tag, params?) {
    var datas: any = {
      groupId: Events.groupId,
      actId: this.actId,
      token: Config.userInfo.token
    }
    switch (tag) {
      case INFO:
        datas.rewardId = this.rewardId.last
        break;
      case JOIN:
        datas.step = params.step
        datas.rewardId = this.rewardId[params.step]
        break;
    }
    return Http.instance.getActivity(tag, datas).then(data => {
      if (data.code === 200) {
        var is200 = data.code === 200
        switch (tag) {
          case INFO:
            this.info = is200 ? data.state : null
            break;
          case CDKEYS:
            this.history = is200 ? data.state : []
        }
      }
      return data
    })
  }

}

class Event2 extends Events {

  static _ins
  static get instance(): Event2 {
    return this._ins ? this._ins : new Event2;
  }
  constructor() {
    super();
    Event2._ins = this
  }

  /**
   * 活动键值
   */
  protected _eventIndex = 1

  /**
   * 当前期数 0,1,2
   */
  private _issue: number = null
  private _systemTicket = []
  private _userTicket = []

  get systemTicket(): number[][] {
    return this._systemTicket
  }
  infoInit(state: InfoState) {
    this.info = state
    this.setUserTicket(state.UserTicket)
    var systemTicket: object = state.SystemTicket
    var keys: string[] = Object.keys(systemTicket)
    if (keys.length) {
      keys.forEach(step => {
        this._systemTicket[Number(step)] = Array.from(systemTicket[step]).map(index => Number(index))
      })
      var issue = Number(keys.last) + 1
      this._issue = Math.min(issue, 2)
    } else {
      this._issue = 0
    }
    return this._issue
  }

  get userTicket(): number[][] {
    return this._userTicket
  }
  setUserTicket(userTicket: object) {
    var keys: string[] = Object.keys(userTicket)
    if (keys.length) {
      keys.forEach(step => {
        this._userTicket[Number(step)] = Array.from(userTicket[step]).map(index => Number(index))
      })
    }
  }

  get issue() {
    return this._issue
  }

  public gotRewardMap = {
    0: false,
    1: false,
    2: false
  }

  queryEvent(tag, params?) {
    var datas: any = {
      groupId: Events.groupId,
      actId: this.actId,
      token: Config.userInfo.token
    }
    switch (tag) {
      case INFO:
        datas.rewardId = this.rewardId.last
        break;
      case JOIN:
        datas.step = params.step
        if (params.ticket) datas.ticket = params.ticket
        if (params.rewardId) datas.rewardId = params.rewardId
        break;
    }
    return Http.instance.getActivity(tag, datas).then(data => {
      var is200 = data.code === 200
      switch (tag) {
        case INFO:
          data.state.issue = is200 ? this.infoInit(data.state) : 0
          this.info = data.state
          break;
        case CDKEYS:
          if (is200) {
            this.history = data.state
            if (this.history.length) {
              this.history.forEach(item => {
                var issue = item.extInfo.step
                this.gotRewardMap[issue] = true
              });
            }
          } else {
            this.history = []
          }
      }
      return data
    })
  }

}

class Event1 extends Events {

  static _ins
  static get instance(): Event1 {
    return this._ins ? this._ins : new Event1;
  }
  constructor() {
    super();
    Event1._ins = this
  }

  /**
   * 活动键值
   */
  protected _eventIndex = 0

  queryEvent(tag, params?) {
    var datas: any = {
      groupId: Events.groupId,
      actId: this.actId,
      token: Config.userInfo.token
    }
    switch (tag) {
      case INFO:
        datas.rewardId = this.rewardId.last
        break;
      case JOIN:
        datas.rewardId = this.rewardId.last
        break;
    }
    return Http.instance.getActivity(tag, datas).then(data => {
      var is200 = data.code === 200
      switch (tag) {
        case INFO:
          this.info = is200 ? data.state : null
          break;
        case CDKEYS:
          this.history = is200 ? data.state : []
      }
      return data
    })
  }

}


class Config {

  static appId = 10092
  static fbId = '1088475561284955'
  static version = 'de'

  static fbRedirectUrl = (function () {
    return window['isMobile'] ? 'http://pmfr.pocketgamesol.com/activity/20180516/mobile/index.html' : 'http://pmfr.pocketgamesol.com/activity/20180516/index.html'
  })()




  // 'http://172.16.3.209:8018/kdyg3ds-fr/activity/' + window.app // 'http://127.0.0.1:9000' 

  static zoneMap: Object = {}
  static zoneList: Array<ZoneInfo> = null
  static roleList: RoleInfo[] = []
  static loginInfo: LoginState = null
  static userInfo: UserInfo = null
  static roleInfo: RoleInfo = null
  static zoneInfo: ZoneInfo = null
}

class Http {

  static _ins
  static get instance(): Http {
    return this._ins ? this._ins : new Http;
  }
  constructor() {
    Http._ins = this
  }

  /**
    * 服务器ip地址
    */
  public serverAdress = 'https://activity.pocketgamesol.com/' //'http://10.10.3.144:8081'

  /**
   * 平台登录
   */
  public pfLoginUrl = this.serverAdress + '/user/sdk/login'

  /**
   * facebookId 登录路径
   */
  public fbLoginUrl = this.serverAdress + '/user/fb/login'

  /**
   * 获取区服 地址
   */
  public zonesUrl = this.serverAdress + '/user/sdk/zones'

  /**
   * 获取角色 地址
   */
  public roleUrl = this.serverAdress + '/user/player/list'


  fbLogin(code): JQuery.jqXHR {
    return $.ajax({
      type: 'GET',
      url: this.fbLoginUrl,
      data: {
        clientId: Config.appId,
        redirectUrl: Config.fbRedirectUrl,
        code: code
      }
    })
  }

  pfLogin(data): JQuery.jqXHR {
    return $.ajax({
      type: 'GET',
      url: this.pfLoginUrl,
      data
    })
  }

  getZones(): JQuery.jqXHR {
    return $.ajax({
      type: 'GET',
      url: this.zonesUrl,
      data: {
        appId: Config.appId,
        token: Store.instance.getItem('token')
      }
    })
  }

  getRole(data): JQuery.jqXHR {
    return $.ajax({
      type: 'GET',
      url: this.roleUrl,
      data
    })
  }

  getActivity(path, data): JQuery.Deferred<EventData> {
    var promise = $.Deferred()
    $.ajax({
      type: 'GET',
      url: this.serverAdress + '/activity/' + path,
      data
    }).then(data => {
      promise.resolve({
        code: data.code,
        state: data.state
      })
    })
    return promise
  }

}

class Login {

  static _ins
  static get instance(): Login {
    return this._ins ? this._ins : new Login;
  }
  constructor() {
    Login._ins = this
  }

  /**
   * 到期时间 30分钟
   */
  public expire: number = 60 * 60 * 1000 * .5

  _isLogin: boolean = false;
  _isRole: boolean = false;

  /**
   * 判断是否已登录
   */
  isLogin() {
    Config.userInfo = Store.instance.getItem('userInfo')
    if (Config.userInfo) {
      var { userId, token, activetime } = Config.userInfo
      if (userId && token) {
        var active = new Date().getTime() - this.expire;
        if (activetime && active < activetime * 1) {
          return true
        } else {
          Store.instance.clear()
        }
      }
    }
    return false;
  }

  /**
   * 是否选择了角色
   */

  isRole() {
    Config.zoneInfo = Store.instance.getItem('zoneInfo')
    Config.roleInfo = Store.instance.getItem('roleInfo')
    if (Config.zoneInfo && Config.roleInfo) {
      return true
    }
    return false
  }

  checkFbLogin() {
    var fbCode = Utils.instance.getParameterByName('code')
    if (!fbCode) {
      return false
    }
    var promise = $.Deferred()

    Http.instance.fbLogin(fbCode).then(data => {
      promise.resolve(data)
    }).fail(err => {
      promise.resolve({
        code: 400,
        state: err
      })
    })

    return promise
  }

  /**
   * fb登录
   */
  fbLogin() {
    var loginUrl = `//www.facebook.com/v2.6/dialog/oauth?client_id=${Config.fbId}&redirect_uri=${encodeURIComponent(Config.fbRedirectUrl)}&r=${Utils.instance.random}`
    location.href = loginUrl;
  }

  /**
   * 平台登录
   */
  pfLogin(): JQuery.Deferred<EventData> {
    var promise = $.Deferred()
    var userName = window.username.value // = 'Qiong@9266.com'
    var password = window.password.value // = 'qqqqqq'
    password = window.md5.md5(password, 32)
    var version = Config.version
    if (!userName || !password) {
      promise.resolve({
        code: 400,
        state: window.translation.loginInfoErr
      })
    } else {
      Http.instance.pfLogin({
        userName,
        password,
        version
      }).then(data => {
        promise.resolve(data)
      }).fail(err => {
        promise.resolve({
          code: 400,
          state: err
        })
      })
    }
    return promise
  }


}

class Dom {
  static logo = $('.logo')
  static loading = $('.loading')

  static mask = $('.mask')

  static connect = $('.header .btn.gold')
  static logged = $('.header .logged')
  static logout = $('.header .logout')

  // event1
  static event1Btn = $('.event1 .btn')
  // event2
  static event2Overview = $('.event2 .overview')
  static event2Record = $('.event2 .record')
  static event2TimebarItems = $('.event2 .timebar .item')
  static event2PokemonsItems = $('.event2 .pokemons .item')
  static event2PokemonsItemsG = Dom.event2PokemonsItems.find('.poke-g')
  static event2PokemonsItemsL = Dom.event2PokemonsItems.find('.poke-l')
  static event2PokemonsItemsC = Dom.event2PokemonsItems.find('.poke-c')
  static event2PokemonsItemsGL = Dom.event2PokemonsItems.find('.poke-g, .poke-l')
  static event2Submit = $('.event2 .btn')

  // event3
  static event3Card = $('.event3 .card')
  static event3CardBtns = $('.event3 .card .btn')

  // pop
  static x = $('.x')
  static popLogin = $('.pop.login')
  static popCtn = $('.pop.ctn')
  static ctnBox = $('.pop.ctn .ctn')
  static loginBtn = $('.pop .login .btns')

  static popOverview = $('.pop.overview')

  static popServer = $('.pop.server')
  static $server = $('#server')
  static $role = $('#role')
  static serverItem = $('.pop.server .item.server')
  static roleItem = $('.pop.server .item.role')
  static popServerConfirm = $('.pop.server .btn')
}

namespace App {
  export class Main implements MainImplements {
    static _ins
    static get instance(): Main {
      return this._ins ? this._ins : new Main;
    }
    constructor() {
      Main._ins = this
    }

    public activePokeItem = []
    public activePokeItemMap = {}
    public event1CanClick = true
    public event2CanClick = true
    public event3CanClick = true

    init() {
      window.modules = {
        utils: Utils.instance,
        dom: Dom
      }


      this.bindEvents()
      this.setZones()
      this.handlerLogin()
      this.handlerRole()

      var promise = Login.instance.checkFbLogin()
      promise && promise.then(data => {
        this.dataHandler(data, () => {
          this.loginSucc(data)
        }, () => {
          location.href = location.origin + location.pathname
          return 'stop'
        })
      })
    }

    /**
     * 初始化区服信息
     */
    setZones() {
      Http.instance.getZones().then(data => {
        Config.zoneList = data.state
        this.dataHandler(data, () => {
          var str = `<option value="0">Sélectionnez serveur</option>`
          Config.zoneList.forEach((item, i) => {
            var { localName, mainGameZoneId } = item
            Config.zoneMap[mainGameZoneId] = i
            str += `<option value="${mainGameZoneId}">${localName}</option>`
          })
          Dom.$server.html(str)
        })
      })
    }

    dataHandler(data: EventData, succFn?: Function, failFn?: Function) {
      var { code, state } = data

      if (!code) {
        Store.instance.clear()
        location.reload()
        return
      }

      if (code === 200) {
        succFn && succFn()
      }
      else if (code === 300) { // not login
        Store.instance.clear()
        Dom.popServerConfirm.data('role', false)
        Dom.$role.html('')
        window.server.value = '0'
        Login.instance._isLogin = Login.instance._isRole = false
        this.loginCheck()
      }
      else {
        var flag: any = true
        failFn && (flag = failFn())
        if (flag !== 'stop') {
          var statement
          statement = window.translation.codes[code] || (code + ', ' + state)
          this.showErr(statement)
        }

      }
    }

    showErr(message: string, config?: any) {
      if (config && config.align) {
        Dom.ctnBox.css({ 'text-align': config.align })
      } else {
        Dom.ctnBox.css({ 'text-align': 'center' })
      }
      Dom.ctnBox.html(message)
      this.showQueue(Dom.popCtn)
    }

    consoleLog(cs, tag?) {
      tag ? console.log(tag, cs) : console.log(cs)
    }

    userInfoRender() {
      Login.instance._isLogin = true
      Dom.connect.addClass(HIDE)
      Dom.logged.removeClass(HIDE)
      Dom.logged.find('.username span').html(Config.userInfo.userName)
    }

    roleInfoRender() {
      Login.instance._isRole = true
      Dom.logged.find('.zonename, .rolename').removeClass(HIDE)
      Dom.logged.find('.zonename span').html(Config.zoneInfo.localName)
      Dom.logged.find('.rolename span').html(Config.roleInfo.playerName)

      { // event1
        $.when(
          Event1.instance.queryEvent(INFO).done(data => {
            this.dataHandler(
              data,
              this.consoleLog.bind(this, data.state, 'Event1 INFO'),
              this.consoleLog.bind(this, data.state, 'Event1 INFO')
            )
          }).fail(err => {
            console.error(err)
            this.showErr(err)
          }),
          Event1.instance.queryEvent(CDKEYS).then(data => {
            this.dataHandler(
              data,
              this.consoleLog.bind(this, data.state, 'Event1 CDKEYS'),
              this.consoleLog.bind(this, data.state, 'Event1 CDKEYS')
            )
          }).fail(err => {
            console.error(err)
            this.showErr(err)
          })
        ).always(data => {
          if (Event1.instance.history.length) {
            Dom.event1Btn.data('state', 'over')
            Dom.event1Btn.attr('class', 'btn gold')
            Dom.event1Btn.text(window.translation.achieved)
          } else {
            Dom.event1Btn.data('state', 'reward')
            Dom.event1Btn.attr('class', 'btn gold')
            Dom.event1Btn.text(window.translation.get)
          }
        })
      }

      { // event2
        $.when(
          Event2.instance.queryEvent(INFO).done(data => {
            this.dataHandler(
              data,
              this.consoleLog.bind(this, data.state, 'Event2 INFO'),
              this.consoleLog.bind(this, data.state, 'Event2 INFO')
            )
          }).fail(err => {
            console.error(err)
            this.showErr(err)
          }),
          Event2.instance.queryEvent(CDKEYS).then(data => {
            this.dataHandler(
              data,
              this.consoleLog.bind(this, data.state, 'Event2 CDKEYS'),
              this.consoleLog.bind(this, data.state, 'Event2 CDKEYS')
            )
          }).fail(err => {
            console.error(err)
            this.showErr(err)
          })
        ).always(data => {
          this.event2Render(Event2.instance.info.issue)
        })
      }

      { // event3
        $.when(
          Event3.instance.queryEvent(INFO).done(data => {
            this.dataHandler(
              data,
              this.consoleLog.bind(this, data.state, 'Event3 INFO'),
              this.consoleLog.bind(this, data.state, 'Event3 INFO')
            )
          }).fail(err => {
            console.error(err)
            this.showErr(err)
          }),
          Event3.instance.queryEvent(CDKEYS).then(data => {
            this.dataHandler(
              data,
              this.consoleLog.bind(this, data.state, 'Event3 CDKEYS'),
              this.consoleLog.bind(this, data.state, 'Event3 CDKEYS')
            )
          }).fail(err => {
            console.error(err)
            this.showErr(err)
          })
        ).always(data => {
          if (Event3.instance.info.gameLogin.length) { // 可以领奖
            if (Event3.instance.history.length) {
              var rws = {}
              Event3.instance.history.forEach((item, i) => {
                rws[item.rewardId] = true
              })
              Event3.instance.info.gameLogin.forEach((item, i) => {
                var btn = Dom.event3CardBtns.eq(i)
                if (!rws.hasOwnProperty(Event3.instance.rewardId[i])) {
                  btn.attr('class', 'btn gold')
                  btn.data('state', 'reward')
                  btn.text(window.translation.get)
                } else {
                  btn.attr('class', 'btn gold')
                  btn.data('state', 'over')
                  btn.text(window.translation.achieved)
                }
              })
            } else {
              Event3.instance.info.gameLogin.forEach((item, i) => {
                var btn = Dom.event3CardBtns.eq(i)
                btn.attr('class', 'btn gold')
                btn.data('state', 'reward')
              })
            }


          }
        })
      }


    }

    handlerLogin(flag?) {
      if (flag) {
        this.userInfoRender()
      } else {
        if (Login.instance.isLogin()) {
          this.userInfoRender()
        } else {
          Dom.connect.removeClass(HIDE)
        }
      }
    }

    handlerRole(flag?) {
      if (flag) {
        this.roleInfoRender()
      } else {
        if (Login.instance.isRole()) {
          this.roleInfoRender()
        }
      }
    }

    queue = []
    showQueue(dom) {
      this.queue.push(dom)
      dom.removeClass(HIDE)
      var length = this.queue.length
      if (length === 1) {
        Dom.mask.removeClass(HIDE)
      } else {
        this.queue[length - 2].addClass('sink')
      }
    }

    removeQueue() {
      if (this.queue.length) {
        var hide = this.queue.pop()
        var length = this.queue.length
        hide.addClass('hide')
        if (!length) {
          Dom.mask.addClass(HIDE)
        } else {
          this.queue[length - 1].removeClass('sink')
        }
      }
    }

    canChage = true
    zoneId = null

    serverChange() {

      if (Config.roleList[window.server.value]) {
        Dom.$role.html(Config.roleList[window.server.value][0].playerName)
        Dom.popServerConfirm.data('role', true)
        return
      }

      if (this.canChage) {
        this.canChage = false
        this.zoneId = window.server.value
        Dom.$role.html(window.translation.querying)
        Dom.popServerConfirm.data('role', false)

        Http.instance.getRole({
          appId: Config.appId,
          gameZoneId: this.zoneId,
          token: Config.userInfo.token
        }).then(data => {
          // dom
          Dom.$role.html('')
          this.canChage = true

          if (data.state.length) {
            Config.roleList[this.zoneId] = data.state
          }

          if (!Config.roleList[this.zoneId]) {
            Dom.$role.html(window.translation.noRole)
            Dom.popServerConfirm.data('role', false)
            return
          }

          this.dataHandler(data, () => {
            if (this.zoneId === window.server.value) {
              Dom.$role.html(Config.roleList[this.zoneId][0].playerName)
              Dom.popServerConfirm.data('role', true)
            }
          })
          if (this.zoneId !== window.server.value) {
            this.serverChange()
          }
        }).fail(err => {
          this.showErr(window.translation.unknown)
          this.canChage = true
          if (this.zoneId !== window.server.value) {
            this.serverChange()
          }
        })
      }
    }


    bindEvents() {

      Dom.loading.addClass('loader')

      Dom.logo.click(() => {
        window.open('https://www.facebook.com/TrainerBattle/')
      })
      Dom.connect.click(() => {
        this.showQueue(Dom.popLogin)
      })

      Dom.x.click(() => {
        this.removeQueue()
      })

      Dom.popServerConfirm.click((e) => {
        if (!Dom.popServerConfirm.data('role')) return
        Config.roleInfo = Config.roleList[window.server.value][0]
        Config.zoneInfo = Config.zoneList[Config.zoneMap[window.server.value]]
        Store.instance.setItem('roleInfo', Config.roleInfo)
        Store.instance.setItem('zoneInfo', Config.zoneInfo)
        this.removeQueue()
        this.handlerRole(true)
      })

      Dom.logout.click(function () {
        Store.instance.clear()
        location.reload()
      })

      Dom.$server.change(() => {
        this.serverChange()
      })

      Dom.loginBtn.on('click', '.btn', (e) => {
        var target = $(e.target)
        var isFb = target.hasClass('fb')
        if (isFb) {
          Login.instance.fbLogin()
        } else {
          Login.instance.pfLogin().then(data => {
            this.dataHandler(data, () => {
              this.loginSucc(data)
            })
          })
        }
      })

      Dom.event1Btn.click(() => {
        if (!this.loginCheck()) return
        var state = Dom.event1Btn.data('state')
        if (this.event1CanClick && state) {
          var info = Event1.instance.info
          if (info && info.joinTime.sumTime !== 0) {
            this.event1CanClick = false
            Event1.instance.queryEvent(JOIN).then(data => {
              this.dataHandler(data, () => {
                Event1.instance.info = {
                  joinTime: {
                    sumTime: 0
                  }
                }

                Event1.instance.history = [{
                  cdKeys: data.state.cdKeys
                }]

                Dom.event1Btn.data('state', 'over')
                Dom.event1Btn.attr('class', 'btn gold')
                Dom.event1Btn.text(window.translation.achieved)

                this.showErr(data.state.cdKeys)
              }, () => {
                this.showErr(window.translation.event1_not_achieve)
                return 'stop'
              })
              this.event1CanClick = true
            }).fail(err => {
              this.event1CanClick = true
              this.showErr(window.translation.noRole)
            })
          } else {
            var history = Event1.instance.history.last
            this.showErr(history.cdKeys)
          }
        }

      })

      Dom.event3Card.on('click', '.btn', (e) => {
        if (!this.loginCheck()) return
        var item = $(e.target)
        var state = item.data('state')
        if (state) {
          switch (state) {
            case 'reward':
              var step = Number(e.target.dataset.index)
              if (this.event3CanClick) {
                this.event3CanClick = false
                Event3.instance.queryEvent(JOIN, { step }).then(data => {
                  this.dataHandler(data, () => {
                    this.showErr(window.translation.emailOk)
                    var btn = Dom.event3CardBtns.eq(step)
                    btn.data('state', 'over')
                    btn.text(window.translation.achieved)
                  })
                }).done(() => {
                  this.event3CanClick = true
                }).fail((err) => {
                  this.event3CanClick = true
                  console.error(err)
                  this.showErr(window.translation.unknown)
                })
              }
              break;
            case 'over':
              this.showErr(window.translation.emailOk)
          }

        }
      })

      Dom.event2TimebarItems.click((e) => {
        if (!this.loginCheck()) return
        var item = $(e.target)
        if (!item.hasClass('item')) item = $(e.target).parents('.item')
        var index = item.index()
        if (index > Event2.instance.issue) {
          this.showErr(window.translation.notStart)
        } else {
          this.event2Render(index)
        }
      })

      Dom.event2PokemonsItemsGL.click((e) => {
        if (!this.loginCheck()) return
        e.stopPropagation()

        if (this.timebarIndex === Event2.instance.issue) {
          var userInfo = Event2.instance.userTicket[this.timebarIndex]
          if (!userInfo) {
            var item = $(e.target)
            var index
            var isL = item.hasClass('poke-l')
            var light, gray
            if (isL) {
              light = item
              gray = item.siblings('.poke-g')
              index = Dom.event2PokemonsItemsL.index(item)
            } else {
              gray = item
              light = item.siblings('.poke-l')
              index = Dom.event2PokemonsItemsG.index(item)
            }
            var prop: string = index + ''
            var i
            if (this.activePokeItemMap.hasOwnProperty(prop)) {
              i = this.activePokeItem.indexOf(index)
              this.activePokeItem.splice(i, 1)
              var { gray, index, light } = this.activePokeItemMap[prop]
              this.pokeItemRender(light, gray)
              delete this.activePokeItemMap[prop]
            } else {
              this.pokeItemRender(gray, light)
              this.activePokeItemMap[prop] = { gray, index, light }
              i = this.activePokeItem.indexOf(index)
              if (i === -1) {
                this.activePokeItem.push(index)
              }
              if (this.activePokeItem.length > 5) {
                prop = this.activePokeItem.shift() + ''
                var { gray, index, light } = this.activePokeItemMap[prop]
                this.pokeItemRender(light, gray)
                delete this.activePokeItemMap[prop]
              }
            }
          }
        }
      })

      Dom.event2Submit.click((e) => {
        if (!this.loginCheck()) return
        var state = Dom.event2Submit.data('state')
        if (state) {
          switch (state) {
            case 'reward':
              this.getGuessReward()
              break;
            case 'join':
              this.joinGuessAct()
              break;
          }
        }
      })

      Dom.event2Overview.click((e) => {
        this.showQueue(Dom.popOverview)
      })

      Dom.event2Record.click((e) => {
        if (!this.loginCheck()) return
        var str = ''
        for (var issue in Event2.instance.gotRewardMap) {
          var isGet = Event2.instance.gotRewardMap[issue]
          str += window.translation.issues[<any>issue * 1]
          str += isGet ? window.translation.congratulations : window.translation.pity
          str += '<br>'
        }
        this.showErr(str, { align: 'left' })
      })

    }

    loginSucc(data) {
      this.removeQueue()
      this.showQueue(Dom.popServer)
      Config.loginInfo = data.state
      var activetime = new Date().getTime()
      var userInfo = Object.assign({ activetime }, Config.loginInfo)
      Config.userInfo = userInfo
      Store.instance.setItem('userInfo', userInfo)
      this.handlerLogin(true)
    }

    pokeItemRender(hide: JQuery<HTMLElement>, show: JQuery<HTMLElement>) {
      hide.addClass(HIDE)
      show.removeClass(HIDE)
    }

    loginCheck() {
      if (!Login.instance._isLogin) {
        this.showQueue(Dom.popLogin)
        return false;
      }
      if (!Login.instance._isRole) {
        this.showQueue(Dom.popServer)
        return false;

      }
      return true
    }


    // event2
    timebarIndex: number
    event2Render(index) {
      this.timebarIndex = index
      this.timebarRender()
      this.crownRender()
      this.userChooseRender()
      this.event2SubmitRender()
    }

    event2SubmitRender() {
      var systemInfo = Event2.instance.systemTicket[this.timebarIndex]
      var userInfo = Event2.instance.userTicket[this.timebarIndex]
      var isGotReward = Event2.instance.gotRewardMap[this.timebarIndex]
      var submit = Dom.event2Submit
      if (systemInfo) {
        if (userInfo) {
          var count = 0
          systemInfo.forEach(number => {
            if (userInfo.indexOf(number) !== -1) count++
          })
          if (count >= 3 && !isGotReward) {
            submit.attr('class', 'btn gold')
            submit.data('state', 'reward')
            submit.data('reward', count - 3)
            submit.html(window.translation.reward)
            return
          }
        }
        submit.attr('class', 'btn ed')
        submit.data('state', 'over')
        submit.html(window.translation.over)
      } else {
        if (userInfo) {
          submit.attr('class', 'btn gold')
          submit.data('state', 'over')
          submit.html(window.translation.joinSucc)
          return
        }
        submit.attr('class', 'btn gold')
        submit.data('state', 'join')
        submit.html(window.translation.join)

      }
    }

    getGuessReward() {

      if (this.event2CanClick) {
        this.event2CanClick = false
        var step = this.timebarIndex
        var submit = Dom.event2Submit

        var rewardId = Event2.instance.rewardId[
          submit.data('reward')
        ]
        Event2.instance.queryEvent(JOIN, { step, rewardId }).then(data => {
          this.dataHandler(data, () => {
            this.showErr(window.translation.emailOk)
            submit.attr('class', 'btn ed')
            submit.data('state', 'over')
            Event2.instance.gotRewardMap[step] = true
            submit.html(window.translation.over)
          })
        }).done(() => {
          this.event2CanClick = true
        }).fail((err) => {
          console.log(err)
          this.showErr(window.translation.unknown)
          this.event2CanClick = true
        })
      }

    }

    joinGuessAct() {
      var length = this.activePokeItem.length
      if (length < 5) {
        this.showErr(window.translation.noFive)
        return
      }
      if (this.event2CanClick) {
        this.event2CanClick = false
        var submit = Dom.event2Submit
        var ticket = this.activePokeItem.sort().join('')
        var step = this.timebarIndex
        Event2.instance.queryEvent(JOIN, { ticket, step }).then(data => {
          this.dataHandler(data, () => {
            this.showErr(window.translation.joinSucc)
            submit.attr('class', 'btn gold')
            submit.data('state', 'reward')
            submit.html(window.translation.reward)
          }, () => {
            if (data.code === 1005) {
              this.showErr(window.translation.wait)
              return 'stop'
            }
          })
        }).done(() => {
          this.event2CanClick = true
        }).fail((err) => {
          console.log(err)
          this.showErr(window.translation.unknown)
          this.event2CanClick = true
        })
      }

    }

    timebarRender() {
      Dom.event2TimebarItems.eq(this.timebarIndex).removeClass(GRAY).siblings().addClass(GRAY)
    }

    crownRender() {
      var systemInfo = Event2.instance.systemTicket[this.timebarIndex]
      Dom.event2PokemonsItemsC.addClass(HIDE)
      if (systemInfo) {
        systemInfo.forEach(index => {
          Dom.event2PokemonsItemsC.eq(index).removeClass(HIDE)
        })
      }
    }

    userChooseRender() {
      var userInfo = Event2.instance.userTicket[this.timebarIndex]
      if (userInfo) {
        this.pokeItemRender(Dom.event2PokemonsItemsL, Dom.event2PokemonsItemsG)
        userInfo.forEach(index => {
          this.pokeItemRender(Dom.event2PokemonsItemsG.eq(index), Dom.event2PokemonsItemsL.eq(index))
        })
      } else {
        this.pokeItemRender(Dom.event2PokemonsItemsL, Dom.event2PokemonsItemsG)
        if (this.activePokeItem.length && this.timebarIndex === Event2.instance.issue) {
          this.activePokeItem.forEach(index => {
            this.pokeItemRender(Dom.event2PokemonsItemsG.eq(index), Dom.event2PokemonsItemsL.eq(index))
          })
        }
      }
    }

  }

  export class Button {
    constructor(btn, props, fn?: Function, mode = 0) {
      this.button = btn
      if (props && Object.prototype.toString.call(props) !== "[object Array]") {
        props = [props]
      }
      this.props = props || []
      this.clickFn = fn || function () { }
      this.create()
      this.changeMdoe(mode)
    }

    static defaultClassName: string[] = ["btn"]
    static btnList: JQuery<HTMLElement>[] = []

    public props: {
      class?: string[]
      text?: string
    }[]
    public button: JQuery<HTMLElement>;
    public index: number
    public mode: number
    public clickFn: Function
    public clickLimit: number = 500
    public limit(clickLimit) {
      this.clickLimit = clickLimit
    }

    get curProp() {
      return this.props[this.mode]
    }

    initAction() {
      this.curProp.class = Button.defaultClassName.concat(this.curProp.class || [])
      this.button.attr('class', this.curProp.class.join(' '))
      if (this.curProp.text) {
        this.button.text(this.curProp.text)
      }
    }

    create() {
      var len = Button.btnList.push(this.button)
      this.index = len - 1;
      this.button.data('index', this.index)

      this.button.click(e => {
        if (this.clickLimit > 0) {
          this.clickFn.apply(this, [e])
          setTimeout(this.limit.bind(this, this.clickLimit), this.clickLimit)
          this.clickLimit = -1
        }
      })

    }

    changeMdoe(mode) {
      this.mode = mode
      this.initAction()
    }

  }
}


if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
  window['isMobile'] = true
}


App.Main.instance.init()